module maths.Misc;

private {
	import std.math;
}



const real deg2rad	= 0.0174532925199432957692369076848861;
const real rad2deg	= 57.2957795130823208767981548141052;
const real pi			= 3.1415926535897932384626433832795;



/**
	Convert the specfied [x y z] coordinates to spherical [pi theta r]
*/
void cartesianToSpherical(real x, real y, real z, real* phi, real* theta, real* r)
out {
	assert (*phi >= -pi - 0.001 && *phi <= pi + 0.001);
	assert (*theta >= -0.001 && *theta <= pi + 0.001);
}
body {
	*r			= sqrt(x*x+y*y+z*z);
	*phi		= atan2(y, x);
	*theta	= acos(z / *r);
}


/**
	Convert the specfied [x y z] coordinates to spherical [pi theta]
*/
void cartesianToSpherical(real x, real y, real z, real* phi, real* theta)
in {
	real r = sqrt(x*x+y*y+z*z);
	assert (r >= 0.999 && r <= 1.001);
}
out {
	assert (*phi >= -pi - 0.001 && *phi <= pi + 0.001);
	assert (*theta >= -0.001 && *theta <= pi + 0.001);
}
body {
	*phi		= atan2(y, x);
	*theta	= acos(z);
}


/**
	'Nearest' interpolation function
	
	Params:
	t == time, a float from [0, 1]
	a == first value
	b == second value
	res == a place to put the result in
	
	Remarks:
	nearestInterp(< 0.5, a, b, res), res == a
	nearestInterp(>= 0.5, a, b, res), res == b
*/
void nearestInterp(T)(float t, T a, T b, inout T res) {
	if (t >= 0.5f) res = b;
	else res = a;
}


/**
	'Linear' interpolation function
	
	Params:
	t == time, a float from [0, 1]
	a == first value
	b == second value
	res == a place to put the result in
	
	Remarks:
	nearestInterp(0, a, b, res), res == a
	nearestInterp(1, a, b, res), res == b
*/
void linearInterp(T)(float t, T a, T b, inout T res) {
	res = a * (1.f - t) + b * t;
}


/**
	Catmull-rom interpolation function
	
	Params:
	t == time, a float from [0, 1]
	a == first value
	b == second value
	c == third value
	d == fourth value
	res == a place to put the result in
*/
void catmullRomInterp(T)(float t, T a, T b, T c, T d, inout T res) {
	res = .5f * (	(b * 2.f) +
						(c - a) * t +
						(a * 2.f - b * 5.f + c * 4.f - d) * t * t +
						(b * 3.f - c * 3.f + d - a) * t * t * t);
}
